package com.peppa.common.grayconfig;

import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.*;
//import com.netflix.zuul.context.RequestContext;
import com.peppa.common.grayconfig.Strategy.Strategy;
import com.peppa.common.grayconfig.Strategy.factory.StrategyFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

import java.util.Map;
import java.util.StringTokenizer;

/**
 * ribbon的自定义策略
 * @author:duge
 *
 */
@Configuration
@ConditionalOnProperty(prefix="peppa",name = "gray", havingValue = "true")
@Scope(value = "prototype")
public class MyGrayBalancerRule extends RoundRobinRule {
    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Value("${graystage:}")
    private String graystagestr;

    @Autowired
    private StrategyFactory strategyFactory;

    public Server choose(ILoadBalancer balancer,Object key) {
        try{
            String threadname = Thread.currentThread().getName();
            if (threadname.indexOf("zipkin")>=0){
                return chooseDeault(balancer,key);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        try {
            String whiteliststr = ThreadAttributes.getHeaderValue(Strategy.TAG_WHITELIST);
            logger.debug("白名单:{}", whiteliststr);
            //如果有白名单，则走白名单，后面不走了
            if (whiteliststr != null) {
                StringTokenizer stringTokenizer = new StringTokenizer(whiteliststr, Strategy.DELIM_ITEM);
                while (stringTokenizer.hasMoreElements()) {
                    String whitestrategy = stringTokenizer.nextToken().trim();
                    //如果白名单中有DEF，则如果不符合条件就选择任意一个服务
                    if (whitestrategy.equals(Strategy.DEFAULT_STRATEGY)) {
                        return chooseDeault(balancer, key);
                    } else {
                        Strategy strategy = strategyFactory.getStrategy(whitestrategy);
                        if (strategy == null) {
                            logger.debug("白名单策略:{}不存在", whitestrategy);
                            continue;
                        }
                        Server server = strategy.getServer(balancer);
                        if (server != null)
                            return server;
                    }
                }
                logger.debug("白名单中的策略没有命中任何服务器{}", whiteliststr);
                return null;
            }
            //没有白名单的情况，按顺序走其他策略
            String blackliststr = ThreadAttributes.getHeaderValue(Strategy.TAG_BLACKLIST);
            logger.debug("黑名单:{}", blackliststr);
            for (Strategy strategy : strategyFactory.getAllStrategy()
            ) {
                String strategyname = strategy.getName();
                //黑名单策略忽略
                if (blackliststr != null) {
                    if (blackliststr.indexOf(strategyname) >= 0)
                        continue;
                }
                logger.debug("{}策略生效！", strategyname);
                Server server = strategy.getServer(balancer);
                if (server != null)
                    return server;
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return chooseDeault(balancer,key);
    }
    private Server chooseDeault(ILoadBalancer balancer,Object key) {
        Server server =super.choose(balancer,key);
        try{
            String threadname = Thread.currentThread().getName();
            if (threadname.indexOf("zipkin")>=0){
            }else {
                logger.info("最后缺省随机策略 all server size：{},{}",balancer.getAllServers().size(),server.getHost());
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return server;
//        IRule rule = new RandomRule();
//        rule.setLoadBalancer(balancer);
//        Server server = rule.choose(key);
//        return server;
    }

    @Override
    public Server choose(Object key)
    {
        return choose(getLoadBalancer(), key);
    }

    @Override
    public void initWithNiwsConfig(IClientConfig clientConfig)
    {
        // TODO Auto-generated method stub
//        logger.info("clientConfig"+clientConfig);
    }

}